﻿using System;
using System.IO;
using System.Text;
using System.Xml;
using SysXmlSerializer = System.Xml.Serialization.XmlSerializer;

namespace Winning.SolutionManager.Util
{
    public sealed class XmlSerializer : ISerializer
    {
        private SysXmlSerializer _xmlSerializer;

        public void Serialize(object obj, Stream stream, Encoding encoding)
        {
            if (obj == null) throw new ArgumentNullException("obj");
            if (stream == null) throw new ArgumentNullException("stream");
            if (encoding == null) encoding = Encoding.UTF8;

            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            settings.NewLineChars = Environment.NewLine;
            settings.Encoding = encoding;
            settings.IndentChars = "    ";

            using (XmlWriter xmlWriter = XmlWriter.Create(stream, settings))
            {
                this._xmlSerializer = new SysXmlSerializer(obj.GetType());
                this._xmlSerializer.Serialize(xmlWriter, obj);
            }
        }

        public string Serialize(object obj)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                this.Serialize(obj, stream, Encoding.UTF8);
                stream.Position = 0;
                StreamReader streamReader = new StreamReader(stream, Encoding.UTF8);
                return streamReader.ReadToEnd();
            }
        }

        public void Serialize(object obj, string path, Encoding encoding)
        {
            using (FileStream fileStream = new FileStream(path, FileMode.Create, FileAccess.Write))
            {
                this.Serialize(obj, fileStream, encoding);
            }
        }

        public T Deserialize<T>(Stream stream, Encoding encoding)
        {
            if (stream == null) throw new ArgumentNullException("stream");
            if (encoding == null) encoding = Encoding.UTF8;

            using (StreamReader streamReader = new StreamReader(stream, encoding))
            {
                XmlTextReader xmlTextReader = new XmlTextReader(streamReader);
                this._xmlSerializer = new SysXmlSerializer(typeof(T));
                return (T)this._xmlSerializer.Deserialize(xmlTextReader);
            }
        }

        public T Deserialize<T>(string content)
        {
            using (MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(content)))
            {
                return this.Deserialize<T>(memoryStream, Encoding.UTF8);
            }
        }

        public T Deserialize<T>(string path, Encoding encoding)
        {
            using (FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read))
            {
                return this.Deserialize<T>(fileStream, encoding);
            }
        }
    }
}